package com.lagou.filter;

import lombok.extern.java.Log;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.couchbase.CouchbaseProperties;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@Component
@Slf4j
public class RequestLimitFilter implements GlobalFilter, Ordered {

    /*IP防暴暴刷（限制单个客户端IP在最近1分钟内请求注册接口不能超过10次  -- > 简化成每6秒,减少一次缓存中的数字）*/
    private static final Map<String, Integer> LOCAL_CACHE = new ConcurrentHashMap<>();

    private boolean isRun = false;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("RequestLimitFilter begin");

        if(!isRun){
            //第一次访问,启动定时器,每6秒对缓存中的数字进行一次处理
            isRun = true;
            new Timer().start();
        }
        log.info("uri : " + exchange.getRequest().getURI().getPath());
        //非注册请求直接放行
        if(!exchange.getRequest().getURI().getPath().startsWith("/user/register/")){
            // 合法请求，放行，执行后续的过滤器
            log.info("RequestLimitFilter 放行");
            return chain.filter(exchange);
        }

        //如果请求路径是/user/register,那么开始根据ip进行判断
        String ip = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
        Integer count = LOCAL_CACHE.get(ip);
        if(count > 10){
            exchange.getResponse().setStatusCode(HttpStatus.SEE_OTHER);
            String data = "您频繁进⾏注册，请求已被拒绝";
            DataBuffer wrap = exchange.getResponse().bufferFactory().wrap(data.getBytes());
            return exchange.getResponse().writeWith(Mono.just(wrap));
        }  else {
            LOCAL_CACHE.put(ip, count + 1);
        }
        log.info("RequestLimitFilter 放行");
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }

static class Timer extends Thread{
    @Override
    public void run(){
        //在run方法填写要执行的操作
        while (true){
            log.info("开始处理缓存");
            try {
                Thread.sleep(6000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Set<String> strings = LOCAL_CACHE.keySet();
            for (String ip :strings) {

                LOCAL_CACHE.put(ip, LOCAL_CACHE.get(ip) - 1);
            }
        }
    }

}
}
